package com.zhuqi.collection;

import org.springframework.util.ObjectUtils;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author : ZhuQi
 * @version : 时间:2021/12/7 15:59 版本:
 * @description : 实现 hashMap
 */
public class ZqMap<K,V> {

    /**
     * 初始化容量
     */
    private static final int INIT_CAPACITY = 16;

    /**
     * 默认负载因子
     */
    private static final float DEFAULT_LOAD_FACTOR = 0.75F;

    /**
     * 转树阈值
     */
    private static final int TREE_THRESHOLD = 8;

    /**
     * 转链表阈值
     */
    private static final int UN_TREE_THRESHOLD = 6;

    /**
     * 当前元素个数
     */
    private AtomicInteger size = new AtomicInteger(0);

    /**
     * 节点数组
     */
    private Node[] table;

    /**
     * 零界点
     */
    int threshold;

    /**
     * 负载因子
     */
    final float loadFactor;

    /**
     * hash
     * 使用 key 的 hashCode 的低16位 亦或 key 值hashCode 的高16位
     * 这是一个扰动函数，使计算后的 hashCode 即拥有高16位的特性，抵16位也保留了特性。
     * 主要目的是降低冲突
     * @param key key
     * @return 加工后的hash值
     */
    static final int hash(Object key){
        int h;
        return key == null ? 0 : (h = key.hashCode()) ^ h >>> 16;
    }

    /**
     * 无参构造
     */
    public ZqMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
    }

    /**
     * 输入 table 长度的构造
     * @param threshold 数据长度
     */
    public ZqMap(int threshold) {
        this(threshold, DEFAULT_LOAD_FACTOR);
    }

    /**
     * 输入容量 和 负载因子 的构造
     * @param threshold  table长度
     * @param loadFactor 负载因子
     */
    public ZqMap(int threshold, float loadFactor) {
        if (threshold < 0 ){
            throw new RuntimeException("初始化容量输入有误");
        } else {
            if (threshold > 1000000000) {
                threshold = 1000000000;
            }
            if (!(loadFactor <= 0.0F) && !Float.isNaN(loadFactor)) {
                this.loadFactor = loadFactor;
                this.threshold = threshold;
            } else {
                throw new RuntimeException("初始化容量输入有误");
            }
        }
    }

    /**
     * 插入数据
     * @param key key
     * @param value value
     */
    private void put(K key, V value) {
        int hash = hash(key);
        int n;
        Node[] tab;
        if (ObjectUtils.isEmpty(table) || table.length == 0) {
            n = (tab = this.resize()).length;
        }
    }

    /**
     * 初始化/扩容的方法
     * @return
     */
    private Node<K,V>[] resize() {
        Node<K,V>[] oldTab = table;
        return oldTab;
    }

    private void get(Object key) {

    }



    class Node<K, V> {
        private Node preNode;

        private K key;

        private V value;

        private Node nextNode;

        private Boolean isLinked;

        private Boolean isTreeNode;

        public Node getPreNode() {
            return preNode;
        }

        public void setPreNode(Node preNode) {
            this.preNode = preNode;
        }

        public Object getKey() {
            return key;
        }

        public void setKey(K key) {
            this.key = key;
        }

        public Object getValue() {
            return value;
        }

        public void setValue(V value) {
            this.value = value;
        }

        public Node getNextNode() {
            return nextNode;
        }

        public void setNextNode(Node nextNode) {
            this.nextNode = nextNode;
        }

        public Boolean getLinked() {
            return isLinked;
        }

        public void setLinked(Boolean linked) {
            isLinked = linked;
        }

        public Boolean getTreeNode() {
            return isTreeNode;
        }

        public void setTreeNode(Boolean treeNode) {
            isTreeNode = treeNode;
        }
    }
}
